/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cvut.fel.taskpro.view.controller;

import cz.cvut.fel.taskpro.business.imanager.IAssignmentBusiness;
import cz.cvut.fel.taskpro.business.imanager.ISubjectBusiness;
import cz.cvut.fel.taskpro.business.imanager.IUserBusiness;
import cz.cvut.fel.taskpro.business.imanager.IVersionBusiness;
import cz.cvut.fel.taskpro.business.support.BusinessRuleException;
import cz.cvut.fel.taskpro.data.entity.Assignment;
import cz.cvut.fel.taskpro.data.entity.AssignmentSubmit;
import cz.cvut.fel.taskpro.data.entity.GroupTaskPro;
import cz.cvut.fel.taskpro.data.entity.Student;
import cz.cvut.fel.taskpro.data.entity.Subject;
import cz.cvut.fel.taskpro.data.entity.VersionFile;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

/**
 *  This controller is responsible for final reports. This controller is view 
 * scope and is called as reportStudentBean.
 * @author Tom
 * @version 1.0.0. beta
 */
@ViewScoped
@ManagedBean(name = "reportStudentBean")
public class ReportStudentController extends AbstractFileController implements Serializable {

    private String selectedSubjectCode;
    private List<Subject> subjects;
    private Map<String, Subject> subjectMap;
    private Map<String, GroupTaskPro> groupMap;
    private List<Assignment> unSubmitPersonAssingment;
    private List<Assignment> unSubmitTeamAssingment;
    private List<AssignmentSubmit> submitPersonalAssignmet;
    private List<AssignmentSubmit> submitTeamAssignment;
    private List<AssignmentSubmit.State> stateOfTask;
    private List<Assignment.Type> typeOfTask;
    private AssignmentSubmit selectedSubmitTask;
    private List<VersionFile> versionFiles;
    private List<Student> kantorStudents;
    private List<GroupTaskPro> subjectGroup;
    private String selectedGroupCode;
    private String selectedStudentLogin;
    private Student selectedStudent;
    private Assignment selectUnsubmitTask;
    private int submitPersonalScore;
    private int submitTeamScore;
    private int totalEarnedScore;
    private int totalScore;
    @EJB
    private ISubjectBusiness subjectB;
    @EJB
    private IAssignmentBusiness assignmentB;
    @EJB
    private IVersionBusiness versionB;
    @EJB
    private IUserBusiness userB;
    /**
     * This method initialize class. If this controller use student, then 
     * are show only subject in which is he member of. If this controller use
     * kantor then are show all subject which he teach. This method initialize
     * filter option. Are type and state of assignment are set up.
     */
    @PostConstruct
    public void init() {
        recognizeLogin();
        subjectMap = new HashMap<String, Subject>();
        groupMap = new HashMap<String, GroupTaskPro>();
        stateOfTask = new ArrayList<AssignmentSubmit.State>();
        typeOfTask = new ArrayList<Assignment.Type>();
        try {
            if (loggedKantor != null) {
                subjects = subjectB.getSubjectsByTeacher(loggedKantor);
            } else if (loggedStudent != null) {
                subjects = subjectB.getStudentsSubjects(loggedStudent);
                selectedStudent = loggedStudent;
            }
            Iterator sIt = subjects.iterator();
            while (sIt.hasNext()) {
                Subject currSubject = (Subject) sIt.next();
                subjectMap.put(currSubject.getCode(), currSubject);
            }
        } catch (BusinessRuleException ex) {
            printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
        }
        stateOfTask.add(AssignmentSubmit.State.ACCEPTED);
        stateOfTask.add(AssignmentSubmit.State.REJECTED);
        stateOfTask.add(AssignmentSubmit.State.SUBMITTED);
        typeOfTask.add(Assignment.Type.TEAM);
        typeOfTask.add(Assignment.Type.STUDENT);
        typeOfTask.add(Assignment.Type.GROUP);
    }
    /**
     * This method select subject based on selectedSubjectCode and then 
     * ask business layer for all study group in this subject. This method also
     * load all kantor students if this method call user who is kantor.
     */
    public void chooseSubject() {
        Subject subjectToReport = subjectMap.get(selectedSubjectCode);
        if (subjectToReport != null) {
            try {
                subjectGroup = subjectToReport.getmGroups();
                Iterator groupIt = subjectGroup.iterator();
                while (groupIt.hasNext()) {
                    GroupTaskPro currGroup = (GroupTaskPro) groupIt.next();
                    groupMap.put(currGroup.getCode(), currGroup);
                }
                kantorStudents = userB.getStudentsBySubjectAndKantor(loggedKantor, subjectToReport);
                printSuccMessage("Select subject: ", "Subject " + selectedSubjectCode + " has been successfully selected.");
            } catch (BusinessRuleException ex) {
                printErrMessage(ex.getExceptionCode(), ex.getErrorMessage());
            }
        } else {
            subjectGroup = null;
            kantorStudents = null;
            printErrMessage("Select subject", "No subject was selected");
        }
    }
    /**
     * This method select group based on selected group code. Then all students 
     * in this group are loaded.
     */
    public void chooseGroup() {
        GroupTaskPro selectedGroup = groupMap.get(selectedGroupCode);
        if (selectedGroup == null) {
            kantorStudents = null;
            printErrMessage("Select group", "No group was selected");
        } else {
            kantorStudents = selectedGroup.getMStudents();
            printSuccMessage("Select group: ", "Group " + selectedGroupCode + " has been successfully selected.");
        }

    }
    /**
     * This method ask business layer for find student based on selected student login code.
     * Then is <code>createReport</code> function is called.
     */
    public void chooseStudent() {
        selectedStudent = (Student) userB.findUserByLogin(selectedStudentLogin);
        if (selectedStudent == null) {
            printErrMessage("Select student", "No student were selected");
        } else {
            createReport();
            printSuccMessage("Report ", "The report for student " + selectedStudent.getName() + " " + selectedStudent.getSurname() + " has been successfully created.");
        }
    }
    /**
     * This method create report to selected student in selected subject.
     * This method ask business layer for all submitted assingment which has state
     * which has been set in filter and selected student and were assigned in selected subject.
     * This method also ask business layer for unsubmit and submit assignemtn. Then
     * call function to calculate submitted team score, submitted personla score and
     * all total points.
     */
    public void createReport() {
        Subject subjectToReport = subjectMap.get(selectedSubjectCode);
        if (subjectToReport != null) {
            totalScore = 0;
            submitPersonalAssignmet = assignmentB.getSubmitPersonalAssignmet(selectedStudent, stateOfTask, subjectToReport);
            submitTeamAssignment = assignmentB.getSubmitTeamAssignmet(selectedStudent, stateOfTask, subjectToReport);
            unSubmitPersonAssingment = assignmentB.getUnSubmitPersonalAssignmet(selectedStudent, subjectToReport);
            unSubmitTeamAssingment = assignmentB.getUnSubmitTeamAssignmet(selectedStudent, subjectToReport);
            submitPersonalScore = calculateEarnedPoint(submitPersonalAssignmet);
            submitTeamScore = calculateEarnedPoint(submitTeamAssignment);
            totalScore += calculateTotalPoint(unSubmitTeamAssingment);
            totalScore += calculateTotalPoint(unSubmitPersonAssingment);
            totalEarnedScore = submitPersonalScore + submitTeamScore;
        } else {
            printSuccMessage("Select subject", "No subject was selected");
        }
    }
    /**
     * This method calculate earned point from submitted assignment.
     */
    private int calculateEarnedPoint(List<AssignmentSubmit> assignment) {
        int score = 0;
        Iterator aIt = assignment.iterator();
        while (aIt.hasNext()) {
            AssignmentSubmit asS = (AssignmentSubmit) aIt.next();
            score += asS.getGrade();
            totalScore += asS.getAssignment().getMaxScore();
        }
        return score;
    }
    /**
     * This method calculate all possible points which could be earned.
     */
    private int calculateTotalPoint(List<Assignment> assignment) {
        int score = 0;
        Iterator aIt = assignment.iterator();
        while (aIt.hasNext()) {
            Assignment asS = (Assignment) aIt.next();
            score += asS.getMaxScore();
        }
        return score;
    }
    /**
     * This method load all version from selected submitted assignment.
     */
    public void loadVersion() {
        versionFiles = versionB.getAllVersionFileByAssingment(selectedSubmitTask);
    }

    public String getSelectedSubjectCode() {
        return selectedSubjectCode;
    }

    public void setSelectedSubjectCode(String selectedSubjectCode) {
        this.selectedSubjectCode = selectedSubjectCode;
    }

    public List<Subject> getSubjects() {
        return subjects;
    }

    public void setSubjects(List<Subject> subjects) {
        this.subjects = subjects;
    }

    public List<AssignmentSubmit> getSubmitPersonalAssignmet() {
        return submitPersonalAssignmet;
    }

    public void setSubmitPersonalAssignmet(List<AssignmentSubmit> submitPersonalAssignmet) {
        this.submitPersonalAssignmet = submitPersonalAssignmet;
    }

    public List<AssignmentSubmit> getSubmitTeamAssignment() {
        return submitTeamAssignment;
    }

    public void setSubmitTeamAssignment(List<AssignmentSubmit> submitTeamAssignment) {
        this.submitTeamAssignment = submitTeamAssignment;
    }

    public List<Assignment> getUnSubmitPersonAssingment() {
        return unSubmitPersonAssingment;
    }

    public void setUnSubmitPersonAssingment(List<Assignment> unSubmitPersonAssingment) {
        this.unSubmitPersonAssingment = unSubmitPersonAssingment;
    }

    public List<Assignment> getUnSubmitTeamAssingment() {
        return unSubmitTeamAssingment;
    }

    public void setUnSubmitTeamAssingment(List<Assignment> unSubmitTeamAssingment) {
        this.unSubmitTeamAssingment = unSubmitTeamAssingment;
    }

    public AssignmentSubmit getSelectedSubmitTask() {
        return selectedSubmitTask;
    }

    public void setSelectedSubmitTask(AssignmentSubmit selectedSubmitTask) {
        this.selectedSubmitTask = selectedSubmitTask;
    }

    public List<VersionFile> getVersionFiles() {
        return versionFiles;
    }

    public void setVersionFiles(List<VersionFile> versionFiles) {
        this.versionFiles = versionFiles;
    }

    public Assignment getSelectUnsubmitTask() {
        return selectUnsubmitTask;
    }

    public void setSelectUnsubmitTask(Assignment selectUnsubmitTask) {
        this.selectUnsubmitTask = selectUnsubmitTask;
    }

    public int getSubmitPersonalScore() {
        return submitPersonalScore;
    }

    public void setSubmitPersonalScore(int submitPersonalScore) {
        this.submitPersonalScore = submitPersonalScore;
    }

    public int getSubmitTeamScore() {
        return submitTeamScore;
    }

    public void setSubmitTeamScore(int submitTeamScore) {
        this.submitTeamScore = submitTeamScore;
    }

    public int getTotalEarnedScore() {
        return totalEarnedScore;
    }

    public void setTotalEarnedScore(int totalEarnedScore) {
        this.totalEarnedScore = totalEarnedScore;
    }

    public int getTotalScore() {
        return totalScore;
    }

    public void setTotalScore(int totalScore) {
        this.totalScore = totalScore;
    }

    public List<Student> getKantorStudents() {
        return kantorStudents;
    }

    public void setKantorStudents(List<Student> kantorStudents) {
        this.kantorStudents = kantorStudents;
    }

    public Student getSelectedStudent() {
        return selectedStudent;
    }

    public void setSelectedStudent(Student selectedStudent) {
        this.selectedStudent = selectedStudent;
    }

    public String getSelectedStudentLogin() {
        return selectedStudentLogin;
    }

    public void setSelectedStudentLogin(String selectedStudentLogin) {
        this.selectedStudentLogin = selectedStudentLogin;
    }

    public String getSelectedGroupCode() {
        return selectedGroupCode;
    }

    public void setSelectedGroupCode(String selectedGroupCode) {
        this.selectedGroupCode = selectedGroupCode;
    }

    public List<GroupTaskPro> getSubjectGroup() {
        return subjectGroup;
    }

    public void setSubjectGroup(List<GroupTaskPro> subjectGroup) {
        this.subjectGroup = subjectGroup;
    }
}
